﻿using System.Collections;
using System.Collections.Generic;
using System.Drawing;
using System.IO;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace WenSkin
{
    public class Ini : List<Ini.IniGroup>
    {
        public Ini()
        {
        }
        public Ini(string path)
        {
            Encoding = Encoding.UTF8;
            Path = path;
            Load(path);
        }
        public Ini(string path, Encoding encoding)
        {
            Path = path;
            Encoding = encoding;
            Load(path, encoding);
        }
        public IniItemCollection this[string str] => Find(a => a.Name?.ToUpper() == str?.ToUpper())?.Items;
        public string this[string key, string name]
        {
            get => Find(a => a.Name?.ToUpper() == key?.ToUpper())?.Items[name]?.Value;
            set
            {
                if (!(Find(a => a.Name?.ToUpper() == key?.ToUpper()) is IniGroup group))
                {
                    group = IniGroupItemAdd(key);
                }

                var item = group.Items[name];
                if (name == null || item == null)
                {
                    IniItemAdd(group, name, value);
                    return;
                }
                item.Value = value;
            }
        }

        #region 公有属性
        public string Path { get; private set; }
        public Encoding Encoding { get; private set; }
        public string Text
        {
            get
            {
                StringBuilder str = new StringBuilder();
                foreach (IniGroup group in this)
                {
                    if (!string.IsNullOrEmpty(group.Name))
                        str.Append($"[{group.Name}]\n");

                    foreach (IniItem item in group.Items)
                    {
                        switch (item.Name)
                        {
                            case null:
                                str.Append(item.Value + "\n");
                                break;
                            case "":
                                str.Append($"={item.Value}\n");
                                break;
                            default:
                                str.Append($"{item.Name}={item.Value}\n");
                                break;
                        }
                    }
                }
                var s = str.ToString();
                if (!string.IsNullOrEmpty(s) && s.ToString().EndsWith("\n"))
                {
                    s = s.Remove(s.Length - 1);
                }
                return s;
            }
        }
        #endregion

        public void Load(string path)
        {
            Load(path, Encoding.UTF8);
        }
        public void Load(string path, Encoding encoding)
        {
            Clear();
            if (!File.Exists(path))
                return;

            string[] texts = File.ReadAllLines(path, encoding);

            IniGroup group = null;
            foreach (var text in texts)
            {
                string t = text.Replace(" ", "");
                var idx = text.IndexOf("=");
                if (text.Replace(" ", "").StartsWith("[") && text.Replace(" ", "").EndsWith("]"))
                {
                    group = IniGroupItemAdd(text.Substring(text.IndexOf("[") + 1, text.IndexOf("]") - 1));
                }
                else if (t.StartsWith("!") || t.StartsWith(";") || t.StartsWith("]") || t.StartsWith("//") || string.IsNullOrEmpty(t))
                {
                    group = IniItemAdd(group, null, text);
                }
                else if (idx == -1)
                {
                    group = IniItemAdd(group, null, text);
                }
                else if (idx == 0)
                {
                    group = IniItemAdd(group, "", text);
                }
                else if (idx > 0)
                {
                    group = IniItemAdd(group, text.Substring(0, idx), text.Substring(idx + 1));
                }
            }
        }
        private IniGroup IniGroupItemAdd(string text)
        {
            IniGroup g = new IniGroup() { Name = text };
            Add(g);
            return g;
        }
        private IniGroup IniItemAdd(IniGroup group, string name, string value)
        {
            if (group == null)
            {
                group = IniGroupItemAdd("");
            }
            IniItem item = new IniItem()
            {
                Name = name,
                Value = value,
            };
            group.Items.Add(item);
            return group;
        }
        public void Save()
        {
            SaveAs(Path);
        }
        public void SaveAs(string path)
        {
            SaveAs(path, Encoding);
        }
        public void SaveAs(string path, Encoding encoding)
        {
            File.WriteAllText(path, Text, encoding);
        }
        public class IniItemCollection : List<IniItem>
        {
            public IniItemCollection()
            {
            }
            public IniItem this[string str] => Find(a => a.Name?.ToUpper() == str?.ToUpper());
        }
        public class IniGroup
        {
            private IniItemCollection items;
            public string Name { get; set; }
            public IniItemCollection Items => items ??= new IniItemCollection();
        }
        public class IniItem
        {
            public string Name { get; set; }
            public string Value { get; set; }
        }

        public void IniFormShow()
        {
            Form fm = new Form()
            {
                Size = new System.Drawing.Size(525, 300),
                Text = "Ini设置 - " + this.Path,
            };
            fm.Controls.Add(new IniControl(this) { Dock = DockStyle.Fill });
            fm.ShowDialog();
        }

        public class IniControl : Control
        {
            private Ini Ini;
            public IniControl(Ini ini)
            {
                this.Ini = ini;
                this.Size = new Size(500, 300);
                Initcom();
                if (ini != null)
                    Load();
            }
            private FlowLayoutPanel Flow;
            private void Initcom()
            {
                Button button = new Button()
                {
                    Text = "保存 应用",
                    Dock = DockStyle.Bottom,
                };
                button.Click += (s, e) =>
                {
                    Ini.Save();
                    MessageBox.Show("保存成功!");
                };
                Flow = new FlowLayoutPanel()
                {
                    Dock = DockStyle.Fill,
                    AutoScroll = true,
                    FlowDirection = FlowDirection.LeftToRight,
                };
                this.Controls.Add(Flow);
                this.Controls.Add(button);
            }

            private void Load()
            {
                foreach (var ini in Ini)
                {
                    GroupBox groupBox = new GroupBox()
                    {
                        Text = ini.Name,
                        Width = this.Width - 30,
                        Height = 33 * ini.Items.Count + 40,
                    };
                    FlowLayoutPanel flow = new FlowLayoutPanel()
                    {
                        Dock = DockStyle.Fill,
                    };
                    foreach (var item in ini.Items)
                    {
                        flow.Controls.Add(new IniItemControl(this, item));
                    }
                    groupBox.Controls.Add(flow);
                    Flow.Controls.Add(groupBox);
                }
            }
        }
        public class IniItemControl : Control
        {
            private IniControl owner;
            private IniItem IniItem;
            public IniItemControl(IniControl owner,IniItem iniItem)
            {
                this.owner = owner;
                this.IniItem = iniItem;
                this.Height = 30;
                this.Width = 450;
                this.Initcom();
            }
            private void Initcom()
            {
                Label label = new Label()
                {
                    Text = IniItem.Name,
                    AutoSize = true,
                };
                this.Controls.Add(label);

                TextBox textBox = new TextBox()
                {
                    Width = this.Width - label.Width - 9,
                    Text=IniItem.Value,
                };
                textBox.TextChanged += (s, e) =>
                {
                    this.IniItem.Value = textBox.Text;
                };
                this.Controls.Add(textBox);

                label.Location = new Point(3, (this.Height - label.Height) / 2);
                textBox.Location = new Point(3 + label.Width + 3, (this.Height - textBox.Height) / 2);
            }
        }
    }
}
